home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / gfx / 3d / Skulpt_src.lha / sKulpt-src / File-DirectX.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-03  |  26.5 KB  |  739 lines

  1. #define STRICT
  2.  
  3. // Includes standard Windows
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11.  
  12. // Includes D3D
  13. #define  D3D_OVERLOADS
  14. #include <ddraw.h>
  15. #include <d3d.h>
  16. #include <d3dx.h>
  17.  
  18. // Includes utilitaires D3D
  19. #include "d3dmath.h"
  20. #include "d3dutil.h"
  21. #include "D3DEnum.h"
  22.  
  23. // Ids Resources
  24. //#include "resource.h"
  25.  
  26. // Constantes
  27. #include "const.h"
  28.  
  29. // Types
  30. #include "types.h"
  31.  
  32. // Variables globales projet
  33. #include "vars.h"
  34.  
  35. // Prototypes fonctions autres modules
  36. #include "proto.h"
  37.  
  38. // Macros
  39. #include "macros.h"
  40.  
  41. void vSaveDirectX(void)
  42. {
  43.     int iTriangle, iMtrl;
  44.     static TCHAR sFileName[512];
  45.     FILE* hFile;
  46.  
  47. #ifndef _AMIGA_
  48.     static TCHAR sInitialDir[512] = "";
  49.     TCHAR sCurrentName[512] = "*.x";
  50.  
  51.     // Récupérer le directory courant
  52.     GetCurrentDirectory(sizeof(sInitialDir), sInitialDir);
  53.  
  54.     // Préparer une structure OPENFILENAME
  55.     OPENFILENAME sOFName = { sizeof(OPENFILENAME), NULL, NULL,
  56.                          "Fichiers Scènes DirectX (*.x)\0*.x\0\0",
  57.                          NULL, 0, 1, sCurrentName, 512, sFileName, 512,
  58.                          sInitialDir, "Ouvrir un fichier scène DirectX", 0, 0, 1,
  59.                          ".x", 0, NULL, NULL };
  60.  
  61.     // Choisir un fichier
  62.     if(!GetOpenFileName(&sOFName))
  63.         return;
  64.  
  65.     // Stocker le nom du directory pour le prochain appel
  66.     strcpy(sInitialDir, sCurrentName);
  67. #else
  68.     strcpy(sFileName, "#?.x");
  69.     if (!FSelect("Ouvrir...", sFileName))
  70.         return;
  71. #endif
  72.  
  73.     hFile = fopen(sFileName, "w");
  74.     if (!hFile)
  75.     {
  76.         vTrace("*** E0113 : ouverture fichier %s", sFileName);
  77.         return;
  78.     }
  79.  
  80.     vTrace("*** Fichier scène ouvert : %s", sFileName);
  81.  
  82.     // Garbage collecter
  83.     vCollect();
  84.  
  85.     // Créer le header
  86.     fprintf(hFile, "xof 0303txt 0032\n\nHeader {\n1;\n0;\n1;\n}\n\n");
  87.  
  88.     // Faire la liste des materials
  89.     for (iMtrl = 0 ; iMtrl < iMtrlFirstAvailable ; iMtrl ++)
  90.     {
  91.         D3DMATERIAL7 *hmtrl = &(Materials[iMtrl].mtrl);
  92.         fprintf(hFile, "Material Material_%d {\n%f, %f, %f, %f;;\n%f;\n%f, %f, %f;;\n%f, %f, %f;;\n}\n\n",
  93.             iMtrl,
  94.             hmtrl -> diffuse.r, hmtrl -> diffuse.g, hmtrl -> diffuse.b, hmtrl -> diffuse.a,
  95.             hmtrl -> power,
  96.             hmtrl -> specular.r, hmtrl -> specular.g, hmtrl -> specular.b,
  97.               hmtrl -> emissive.r, hmtrl -> emissive.g, hmtrl -> emissive.b
  98.             );
  99.     }
  100.  
  101.     // Entête frame
  102.     fprintf(hFile, "Frame __sKulpt {\n");
  103.     fprintf(hFile, "FrameTransformMatrix {\n");    
  104.     fprintf(hFile, "1.000000,0.000000,0.000000,0.000000;,\n");
  105.     fprintf(hFile, "0.000000,1.000000,0.000000,0.000000;,\n");
  106.     fprintf(hFile, "0.000000,0.000000,1.000000,0.000000;,\n");
  107.     fprintf(hFile, "0.000000,2.396835,0.000000,1.000000;;\n");
  108.     fprintf(hFile, "}\n\n");
  109.  
  110.     // Entête mesh
  111.     fprintf(hFile, "Mesh __sKulptShape {\n");
  112.  
  113.     // Vertices
  114.     fprintf(hFile, "%d;\n", iVertFirstAvailable);
  115.     for (int iVert = 0 ; iVert < iVertFirstAvailable ; iVert++)
  116.     {
  117.         fprintf(hFile, "%f;%f;%f;",
  118.             Vertices[iVert].vPoint.x, Vertices[iVert].vPoint.y, Vertices[iVert].vPoint.z);
  119.         if (iVert == iVertFirstAvailable - 1)
  120.             fprintf(hFile, ";\n\n");
  121.         else
  122.             fprintf(hFile, ",\n");
  123.     }
  124.  
  125.     // Triangles
  126.     fprintf(hFile, "%d;\n", iTriaFirstAvailable);
  127.     for (iTriangle = 0 ; iTriangle < iTriaFirstAvailable ; iTriangle++)
  128.     {
  129.         fprintf(hFile, "3;%d,%d,%d;",
  130.             Triangles[iTriangle].iSommets[0], Triangles[iTriangle].iSommets[1], Triangles[iTriangle].iSommets[2]);
  131.         if (iTriangle == iTriaFirstAvailable - 1)
  132.             fprintf(hFile, ";\n\n");
  133.         else
  134.             fprintf(hFile, ",\n");
  135.     }
  136.  
  137.     // Mesh Materials
  138.     fprintf(hFile, "MeshMaterialList {\n%d;\n%d;\n", iMtrlFirstAvailable, iTriaFirstAvailable);
  139.     for (iTriangle = 0 ; iTriangle < iTriaFirstAvailable ; iTriangle++)
  140.     {
  141.         fprintf(hFile, "%d", Triangles[iTriangle].iMtrl);
  142.         if (iTriangle == iTriaFirstAvailable - 1)
  143.             fprintf(hFile, ";;\n");
  144.         else
  145.             fprintf(hFile, ",\n");
  146.     }
  147.     for (iMtrl = 0 ; iMtrl < iMtrlFirstAvailable ; iMtrl++)
  148.         fprintf(hFile, "{Material_%d}\n", iMtrl);
  149.     fprintf(hFile, "}\n\n");
  150.  
  151.     // Fin de mesh
  152.     fprintf(hFile, "}\n\n");
  153.  
  154.     // fin de frame
  155.     fprintf(hFile, "}\n\n");
  156.  
  157.     // Animationset
  158.     fprintf(hFile, "AnimationSet skulpt_animset {\n");
  159.     fprintf(hFile, "}\n");
  160.  
  161.  
  162.     fclose(hFile);
  163. }
  164.  
  165. static inline BOOL bStartBy(char *s1, char *s2)
  166. {
  167.     if (!s1 || !s2 || !strlen(s1) || !strlen(s2)) return FALSE;
  168.     return !strncmp(s1, s2, strlen(s2));
  169. }
  170.  
  171. void vLoadDirectX(void)
  172. {
  173.     static TCHAR sFileName[512], cBuffer[512];
  174.     FILE* hFile;
  175. #ifndef _AMIGA_
  176.     static TCHAR sInitialDir[512] = "";
  177.     TCHAR sCurrentName[512] = "*.x";
  178.  
  179.     // Récupérer le directory courant
  180.     GetCurrentDirectory(sizeof(sInitialDir), sInitialDir);
  181.  
  182.     // Préparer une structure OPENFILENAME
  183.     OPENFILENAME sOFName = { sizeof(OPENFILENAME), NULL, NULL,
  184.                          "Fichiers Scènes DirectX (*.x)\0*.x\0\0",
  185.                          NULL, 0, 1, sCurrentName, 512, sFileName, 512,
  186.                          sInitialDir, "Ouvrir un fichier scène DirectX", 0, 0, 1,
  187.                          ".x", 0, NULL, NULL };
  188.  
  189.     // Choisir un fichier
  190.     if(!GetOpenFileName(&sOFName))
  191.         return;
  192.  
  193.     // Stocker le nom du directory pour le prochain appel
  194.     strcpy(sInitialDir, sCurrentName);
  195. #else
  196.     strcpy(sFileName, "#?.x");
  197.     if (!FSelect("Ouvrir...", sFileName))
  198.         return;
  199. #endif
  200.  
  201.     hFile = fopen(sFileName, "r");
  202.     if (!hFile)
  203.     {
  204.         vTrace("*** E0114 : ouverture fichier %s", sFileName);
  205.         return;
  206.     }
  207.  
  208.     vTrace("*** Fichier scène ouvert : %s", sFileName);
  209.  
  210.     // Effacer tous les objets présents en mémoire
  211.     vDeleteObjects();
  212.  
  213. #define STATE_IDLE                  0
  214. #define STATE_GET_MESH              1
  215. #define STATE_GET_VERTICES          2
  216. #define STATE_GET_FACES             3
  217. #define STATE_GET_MTRLL_NUM_MAT     4
  218. #define STATE_GET_MTRLL_NUM_FACES   5
  219. #define STATE_GET_MTRLL_FACES       6
  220. #define STATE_GET_MTRLL_MTRL        7
  221. #define STATE_GET_MTRL_DIFFUSE      8
  222. #define STATE_GET_MTRL_POWER        9
  223. #define STATE_GET_MTRL_SPECULAR     10
  224. #define STATE_GET_MTRL_EMISSIVE     11
  225. #define STATE_GET_MTRL_END          12
  226. #define STATE_GET_NCOORDS           13
  227. #define STATE_GET_COORDS            14
  228. #define STATE_GET_TRANSMAT          15
  229. #define STATE_END_TRANSMAT          16
  230.  
  231.     // lire le fichier
  232.     BOOL bSkip = FALSE, bError = FALSE, bMeshVert;
  233.     int iState = STATE_IDLE,
  234.         iSkipLevel = 0,
  235.         iLine = 0,
  236.         nVert, iVert,
  237.         nTri,  iTri,
  238.         nMtrl, iMtrl,
  239.         nMtrlTri, iMtrlTri,
  240.         nCoords, iCoords,
  241.         *iFirstTriangleOfFan = NULL,
  242.         i1, i2, i3, iVal, iDelta,
  243.         iBaseVert = 0,
  244.         iBaseFace = 0,
  245.         iBaseMtrl = 5,      // Il existe déjà 5 matériaux de base (0-4)
  246.         iFrame = 0;
  247.     D3DMATERIAL7    sMtrl;
  248.     float f1, f2, f3, f4;
  249.     float fEnvXmin = 2000000000., fEnvXmax = -2000000000., fEnvSize;
  250.     float fEnvYmin = 2000000000., fEnvYmax = -2000000000.;
  251.     float fEnvZmin = 2000000000., fEnvZmax = -2000000000.;
  252.  
  253.     D3DMATRIX   MatrixStack[10];
  254.  
  255.     // Parcourir le fichier
  256.     do
  257.     {
  258.         char *p;
  259.  
  260.         // Lire une ligne et incrémenter le compteur
  261.         if (!fgets(cBuffer, sizeof(cBuffer), hFile)) goto __Done;
  262.         iLine++;
  263.  
  264.         // Supprimer les commentaires
  265.         if (p = strstr(cBuffer ,"//")) *p = 0;
  266.  
  267.         // Supprimer les retours chariot, les tabulations, les espaces et les ",; EN FIN DE LIGNE
  268.         while (strlen(cBuffer) && strchr("\r\n\t,;\" ", cBuffer[strlen(cBuffer) - 1])) cBuffer[strlen(cBuffer) - 1] = 0;
  269.  
  270.         // transformer les ',' en ';'
  271.         while (p = strchr(cBuffer, ',')) *p = ';';
  272.  
  273.         // Supprimer les espaces et " en début de ligne
  274.         while (strlen(cBuffer) && (isspace(cBuffer[0]) || cBuffer[0] == '"')) strcpy(cBuffer, cBuffer + 1);
  275.  
  276.         // S'il reste quelque chose dans la ligne
  277.         if (strlen(cBuffer))
  278.         {
  279.             // Si on est en mode skip, sauter la ligne jusqu'à avoir dépilé la dernière '}'
  280.             if (bSkip)
  281.             {
  282.                 if (strchr(cBuffer, '{')) iSkipLevel++;
  283.  
  284.                 if (strchr(cBuffer, '}'))
  285.                 {
  286.                     if (!iSkipLevel)
  287.                         bSkip = FALSE;
  288.                     else
  289.                         iSkipLevel--;
  290.                 }
  291.  
  292.                 goto __Done;
  293.             }
  294.  
  295.             // Passer la chaîne en minuscules
  296.             p = cBuffer;
  297.             while (*p = tolower(*p)) p++;
  298.  
  299.             // Si on est sur la première ligne, vérifier l'en-tête
  300.             if (iLine == 1)
  301.             {
  302.                 if (!(bStartBy(cBuffer, "xof 0302txt 0064") || bStartBy(cBuffer, "xof 0303txt 0032")))
  303.                 {
  304.                     vTrace("*** E0115 : en tête fichier incorrecte");
  305.                     bError = TRUE;
  306.                 }
  307.                 goto __Done;
  308.             }
  309.  
  310.             // Parties non traitées : passer en mode skip pour les sauter
  311.             if (
  312.                 bStartBy(cBuffer, "template") ||
  313.                 bStartBy(cBuffer, "meshnormals") ||
  314.                 bStartBy(cBuffer, "header") ||
  315.                 bStartBy(cBuffer, "animationset ")
  316.                )
  317.             {
  318.                 // aller jusqu'au '{', qui peut être sur une ligne plus loin
  319.                 while (!strchr(cBuffer, '{')) fgets(cBuffer, sizeof(cBuffer), hFile);
  320.                 bSkip = TRUE;
  321.                 goto __Done;
  322.             }
  323.  
  324.             // Frame : Incrémenter le compteur de nesting frames après avoir réglé la transformmatrix sur l'identité
  325.             if (bStartBy(cBuffer, "frame "))
  326.             {
  327.                 vTrace("Décodage frame [%s], frame nesting %d", strchr(cBuffer, ' ') ? strchr(cBuffer, ' ') + 1 : "<noname>", iFrame);
  328.                 D3DUtil_SetIdentityMatrix(MatrixStack[iFrame++]);
  329.                 while (!strchr(cBuffer, '{')) fgets(cBuffer, sizeof(cBuffer), hFile);
  330.                 goto __Done;
  331.             }
  332.  
  333.             // frametransformmatrix : lire la matrice
  334.             if (bStartBy(cBuffer, "frametransformmatrix"))
  335.             {
  336.                 while (!strchr(cBuffer, '{')) fgets(cBuffer, sizeof(cBuffer), hFile);
  337.                 iState = STATE_GET_TRANSMAT;
  338.                 i1 = 0;
  339.                 goto __Done;
  340.             }
  341.  
  342.             // transformmatrix, lecture d'une ligne de la matrice. Si le compte est bon, revenir dans IDLE
  343.             if (iState == STATE_GET_TRANSMAT && (4 == sscanf(cBuffer, "%f;%f;%f;%f", &f1, &f2, &f3, &f4)))
  344.             {
  345.                 MatrixStack[iFrame - 1].m[i1][0] = f1;
  346.                 MatrixStack[iFrame - 1].m[i1][1] = f2;
  347.                 MatrixStack[iFrame - 1].m[i1][2] = f3;
  348.                 MatrixStack[iFrame - 1].m[i1][3] = f4;
  349.                 if (++i1 >= 4)
  350.                 {
  351.                     // Rétablir la matrice Right-Hand
  352.                     MatrixStack[iFrame - 1].m[0][2] *= -1.0f;
  353.                     MatrixStack[iFrame - 1].m[2][0] *= -1.0f;
  354.                     MatrixStack[iFrame - 1].m[1][2] *= -1.0f;
  355.                     MatrixStack[iFrame - 1].m[2][1] *= -1.0f;
  356.                     MatrixStack[iFrame - 1].m[3][2] *= -1.0f;
  357.  
  358.                     iState = STATE_END_TRANSMAT;
  359.                 }
  360.                 goto __Done;
  361.             }
  362.  
  363.             // Mesh : réinitialiser les compteurs de vert, tri, passer en attente du nombre de vertices
  364.             if (iState == STATE_IDLE && bStartBy(cBuffer, "mesh "))
  365.             {
  366.                 iState = STATE_GET_MESH;
  367.                 iVert = iTri = iDelta = 0;
  368.                 vTrace("\tDécodage mesh [%s]", strchr(cBuffer, ' ') ? strchr(cBuffer, ' ') + 1 : "<noname>");
  369.                 bMeshVert = FALSE;
  370.                 while (!strchr(cBuffer, '{')) fgets(cBuffer, sizeof(cBuffer), hFile);
  371.                 goto __Done;
  372.             }
  373.  
  374.             if (iState == STATE_GET_MESH)
  375.             {
  376.                 // Si on n'a pas lu le nombre de vertices, le lire et passer en attente des vertices
  377.                 if (!bMeshVert && (iVal = atoi(cBuffer)))
  378.                 {
  379.                     nVert = iVal;
  380.                     iState = STATE_GET_VERTICES;
  381.                     bMeshVert = TRUE;
  382.                     goto __Done;
  383.                 }
  384.  
  385.                 // Si on n'a pas lu le nombre de triangles, le lire et passer en attente des triangles
  386.                 if (bMeshVert && (iVal = atoi(cBuffer)))
  387.                 {
  388.                     nTri = iVal;
  389.  
  390.                     // Allocation table mapping fan -> tri
  391.                     bError = !(iFirstTriangleOfFan = (int *) malloc(nTri * sizeof(int)));
  392.  
  393.                     iState = STATE_GET_FACES;
  394.                     goto __Done;
  395.                 }
  396.  
  397.                 // MeshMaterialList : passer en attente du nombre de matériaux
  398.                 if (bStartBy(cBuffer, "meshmateriallist"))
  399.                 {
  400.                     iState = STATE_GET_MTRLL_NUM_MAT;
  401.                     while (!strchr(cBuffer, '{')) fgets(cBuffer, sizeof(cBuffer), hFile);
  402.  
  403.                     goto __Done;
  404.                 }
  405.             }
  406.  
  407.             // Mesh, lecture d'un vertex. Si le compte est bon, revenir dans MESH
  408.             if (iState == STATE_GET_VERTICES && (3 == sscanf(cBuffer, "%f;%f;%f", &f1, &f2, &f3)))
  409.             {
  410.                 D3DVECTOR vVect = D3DVECTOR(f1, f2, f3);
  411.  
  412.                 // Appliquer la pile de matrices de transformation
  413.                 for (int iCnt = 0 ; iCnt < iFrame ; iCnt++)
  414.                     D3DMath_VectorMatrixMultiply(vVect, vVect, MatrixStack[iCnt]);
  415.  
  416.                 iMakeVertex(vVect, XDC_FORCENEW);
  417.  
  418.                 f1 = vVect.x ; f2 = vVect.y ; f3 = vVect.z;
  419.                 if (fEnvXmin > f1) fEnvXmin = f1; if (fEnvXmax < f1) fEnvXmax = f1;
  420.                 if (fEnvYmin > f2) fEnvYmin = f2; if (fEnvYmax < f2) fEnvYmax = f2;
  421.                 if (fEnvZmin > f3) fEnvZmin = f3; if (fEnvZmax < f3) fEnvZmax = f3;
  422.  
  423.                 if (++iVert >= nVert) iState = STATE_GET_MESH;
  424.                 goto __Done;
  425.             }
  426.  
  427.             // Mesh, lecture d'un triangle fan
  428.             if (iState == STATE_GET_FACES)
  429.             {
  430.                 int iNum;
  431.                 if (3 == sscanf(cBuffer, "%d;%d;%d;", &iNum, &i1, &i2) && (p = strchr(cBuffer, ';') + 1) && (p = strchr(p, ';') + 1) && (p = strchr(p, ';') + 1))
  432.                 {  
  433.                     i1 += iBaseVert;
  434.                     i2 += iBaseVert;
  435.  
  436.                     // Mémoriser
  437.                     iDelta += iNum - 3;
  438.                     iNum = 0;
  439.  
  440.                     // Pour chaque point du fan, créer le triangle (point, v[i1], v[i2])
  441.                     while (p && 1 == sscanf(p, "%d", &i3) && p)
  442.                     {
  443.                         i3 += iBaseVert;
  444.                         // Si on a plus d'un triangle dans le fan, mettre les suivants à material -1,
  445.                         // pour ensuite les lier au material qui sera défini pour le premier triangle
  446.                         // du fan (malheureusement plus loin !-()
  447.                         iVal = iMakeTriangle(i1, i2, i3, iNum ? -1 : 0);
  448.  
  449.                         // Décaler le fan
  450.                         i2 = i3;
  451.                         p = strchr(p, ';') ? strchr(p, ';') + 1 : 0;
  452.  
  453.                         // Se rappeler qu'on a fait le premier triangle du fan (les prochains dans ce while
  454.                         // seront affectés material -1, cf. ci-dessus)
  455.                         if (!iNum)
  456.                         {
  457.                             iFirstTriangleOfFan[iTri] = iVal;
  458.                             iNum++;
  459.                         }
  460.                     }
  461.                 }
  462.  
  463.                 // Si on a le compte de triangles, revenir en attente des structures MESH
  464.                 if (++iTri >= nTri) iState = STATE_GET_MESH;
  465.                 goto __Done;
  466.             }
  467.  
  468.             // MeshMaterialList : Lecture nombre de matériaux et passage en attente du nombre de faces
  469.             if (iState == STATE_GET_MTRLL_NUM_MAT)
  470.             {
  471.                 if (!(1 == sscanf(cBuffer, "%d", &nMtrl) && nMtrl))
  472.                 {
  473.                     bError = TRUE;
  474.                     vTrace("*** E0094 : lecture nombre matériaux");
  475.                     goto __Done;
  476.                 }
  477.                 iState = STATE_GET_MTRLL_NUM_FACES;
  478.                 goto __Done;
  479.             }
  480.  
  481.             // MeshMaterialList : Lecture nombre de faces et passage en attente des faces
  482.             if (iState == STATE_GET_MTRLL_NUM_FACES)
  483.             {
  484.                 if (!(1 == sscanf(cBuffer, "%d", &nMtrlTri) && nMtrlTri))
  485.                 {
  486.                     bError = TRUE;
  487.                     vTrace("*** E0095 : lecture nombre faces matériaux");
  488.                     goto __Done;
  489.                 }
  490.                 iMtrlTri = 0;
  491.                 iState = STATE_GET_MTRLL_FACES;
  492.                 goto __Done;
  493.             }
  494.  
  495.             // MeshMaterialList : lecture des faces
  496.             if (iState == STATE_GET_MTRLL_FACES && (1 == sscanf(cBuffer, "%d", &i1)))
  497.             {
  498.                 // Application material sur la première face du FAN (les autres seront fillées à la fin du mesh)
  499.                 Triangles[iFirstTriangleOfFan[iMtrlTri]].iMtrl = i1 + iBaseMtrl;
  500.  
  501.                 // Dirty hack pour charger car.x
  502.                 if (nMtrlTri == 1 && nTri > 1)
  503.                 {
  504.                     vTrace("\tSpread material");
  505.                     for (int iTriangle = 0 ; iTriangle < nTri + iDelta ; iTriangle++)
  506.                         Triangles[iTriangle + iBaseFace].iMtrl = i1 + iBaseMtrl;
  507.                 }
  508.  
  509.                 // Si on a le compte, attendre les materials
  510.                 if (++iMtrlTri >= nMtrlTri) iState = STATE_GET_MTRLL_MTRL;
  511.                 goto __Done;
  512.             }
  513.  
  514.             // Material dans MeshMaterialList : passer en attente de la définition DIFFUSE
  515.             if (iState == STATE_GET_MTRLL_MTRL && bStartBy(cBuffer, "material"))
  516.             {
  517.                 while (!strchr(cBuffer, '{')) fgets(cBuffer, sizeof(cBuffer), hFile);
  518.                 iState = STATE_GET_MTRL_DIFFUSE;
  519.                 ZeroMemory(&sMtrl, sizeof(D3DMATERIAL7));
  520.                 goto __Done;
  521.             }
  522.  
  523.             // Material : lecture diffuse et attente power
  524.             if (iState == STATE_GET_MTRL_DIFFUSE
  525.                  && (4 == sscanf(cBuffer, "%f;%f;%f;%f",
  526.                                  &sMtrl.diffuse.r, &sMtrl.diffuse.g, &sMtrl.diffuse.b, &sMtrl.diffuse.a
  527.                                 )
  528.                     )
  529.                )
  530.             {
  531.                 iState = STATE_GET_MTRL_POWER;
  532.                 goto __Done;
  533.             }
  534.  
  535.             // Material : lecture power et attente specular
  536.             if (iState == STATE_GET_MTRL_POWER
  537.                  && (1 == sscanf(cBuffer, "%f",
  538.                                  &sMtrl.power
  539.                                 )
  540.                     )
  541.                )
  542.             {
  543.                 iState = STATE_GET_MTRL_SPECULAR;
  544.                 goto __Done;
  545.             }
  546.  
  547.             // Material : lecture specular et attente emissive
  548.             if (iState == STATE_GET_MTRL_SPECULAR
  549.                  && (3 == sscanf(cBuffer, "%f;%f;%f",
  550.                                  &sMtrl.specular.r, &sMtrl.specular.g, &sMtrl.specular.b
  551.                                 )
  552.                     )
  553.                )
  554.             {
  555.                 sMtrl.specular.a = 1;
  556.                 iState = STATE_GET_MTRL_EMISSIVE;
  557.                 goto __Done;
  558.             }
  559.  
  560.             // Material : lecture emissive, création material, attente fin material
  561.             if (iState == STATE_GET_MTRL_EMISSIVE
  562.                  && (3 == sscanf(cBuffer, "%f;%f;%f",
  563.                                  &sMtrl.emissive.r, &sMtrl.emissive.g, &sMtrl.emissive.b
  564.                                 )
  565.                     )
  566.                )
  567.             {
  568.                 sMtrl.emissive.a = 1;
  569.                 iState = STATE_GET_MTRL_END;
  570.                 sprintf(cBuffer, "X-Mat %d", i1 + iBaseMtrl);
  571.                 iMtrl = iMakeMaterial(&sMtrl, cBuffer, XDC_FORCENEW);
  572.                 goto __Done;
  573.             }
  574.  
  575.             if (iState == STATE_GET_MTRL_END && bStartBy(cBuffer, "texturefilename"))
  576.             {
  577.                 while (!strchr(cBuffer, '{')) fgets(cBuffer, sizeof(cBuffer), hFile);
  578.  
  579.                 if (!strchr(cBuffer, '}')) fgets(cBuffer, sizeof(cBuffer), hFile);
  580.  
  581.                 // Supprimer les commentaires
  582.                 if (p = strstr(cBuffer ,"//")) *p = 0;
  583.  
  584.                 // Supprimer les retours chariot, les tabulations, les espaces et les ",; EN FIN DE LIGNE
  585.                 while (strlen(cBuffer) && strchr("\r\n\t,;\" ", cBuffer[strlen(cBuffer) - 1])) cBuffer[strlen(cBuffer) - 1] = 0;
  586.  
  587.                 // Supprimer les espaces et " en début de ligne
  588.                 while (strlen(cBuffer) && (isspace(cBuffer[0]) || cBuffer[0] == '"')) strcpy(cBuffer, cBuffer + 1);
  589.  
  590.                 strncpy(Materials[iMtrl].sTexName, cBuffer, sizeof(Materials[iMtrl].sTexName));
  591.                 Materials[iMtrl].bTextured = TRUE;
  592.  
  593.                 while (!strchr(cBuffer, '}')) fgets(cBuffer, sizeof(cBuffer), hFile);
  594.  
  595.                 goto __Done;
  596.             }
  597.  
  598.             if (iState == STATE_GET_MESH && bStartBy(cBuffer, "meshtexturecoords"))
  599.             {
  600.                 while (!strchr(cBuffer, '{')) fgets(cBuffer, sizeof(cBuffer), hFile);
  601.  
  602.                 iState = STATE_GET_NCOORDS;
  603.                 goto __Done;
  604.             }
  605.  
  606.             if (iState == STATE_GET_NCOORDS
  607.                  && (1 == sscanf(cBuffer, "%d",
  608.                                  &nCoords
  609.                                 )
  610.                     )
  611.                )
  612.             {
  613.                 iState = STATE_GET_COORDS;
  614.                 iCoords = 0;
  615.                 goto __Done;
  616.             }
  617.  
  618.             if (iState == STATE_GET_COORDS
  619.                  && (2 == sscanf(cBuffer, "%f;%f",
  620.                                  &f1, &f2
  621.                                 )
  622.                     )
  623.                )
  624.             {
  625.                 Vertices[iBaseVert + iCoords].vPointBack.x = f1;
  626.                 Vertices[iBaseVert + iCoords].vPointBack.y = f2;
  627.                 // Si on a le compte de coordonnées, revenir en attente de fin de coordonnées
  628.                 if (++iCoords >= nCoords) iState = STATE_GET_NCOORDS;
  629.                 goto __Done;
  630.             }
  631.  
  632.             if (*cBuffer == '}')
  633.             {
  634.                 switch(iState)
  635.                 {
  636.                     case STATE_GET_MTRL_END :   // Si on a fini le matériau, revenir aux matériaux du MeshMaterialList
  637.                         iState = STATE_GET_MTRLL_MTRL;
  638.                         goto __Done;
  639.  
  640.                     case STATE_END_TRANSMAT :
  641.                         iState = STATE_IDLE;
  642.                         goto __Done;
  643.  
  644.                     case STATE_GET_NCOORDS :     // Si on a fini le TextureCoords, revenir au mesh
  645.                     case STATE_GET_MTRLL_MTRL : // Si on a fini le MeshMaterialList, revenir au mesh
  646.                         iState = STATE_GET_MESH;
  647.                         goto __Done;
  648.  
  649.                     case STATE_GET_MESH :       // Si on a fini le mesh, revenir en idle après avoir consolidé les compteurs globaux
  650.                         vTrace("\tFin mesh : ajout %d vertices, %d trifans, %d triangles, %d matériaux", nVert, nTri, nTri + iDelta, nMtrl);
  651.  
  652.                         // Filler les triangles non fillés parce qu'ils n'étaient pas les premiers des fans
  653.                         for (i1 = 0 ; i1 < nTri + iDelta ; i1++)
  654.                         {
  655.                             int iMat;
  656.                             if (Triangles[i1 + iBaseFace].iMtrl >= 0)
  657.                                 iMat = Triangles[i1 + iBaseFace].iMtrl;
  658.                             else
  659.                                 Triangles[i1 + iBaseFace].iMtrl = iMat;
  660.                         }
  661.  
  662.                         iBaseVert += nVert;
  663.                         iBaseFace += (nTri + iDelta);
  664.                         iBaseMtrl += nMtrl;
  665.                         if (iFirstTriangleOfFan)
  666.                         {
  667.                             free(iFirstTriangleOfFan);
  668.                             iFirstTriangleOfFan = NULL;
  669.                         }
  670.                         iState = STATE_IDLE;
  671.                         goto __Done;
  672.  
  673.                     case STATE_IDLE :
  674.                         if (iFrame > 0)
  675.                         {
  676.                             iFrame--;
  677.                             vTrace("Frame nesting %d", iFrame);
  678.                             goto __Done;
  679.                         }
  680.                 }
  681.  
  682.                 // Autres cas
  683.                 vTrace("*** E0116 : erreur automate d'état, '}' sur état %d et frame %d", iState, iFrame);
  684.                 bError = TRUE;
  685.                 goto __Done;
  686.             }
  687.  
  688.             vTrace("**** I0000 : ligne %d non traitée : [%s] (state = %d, error = %d)", iLine, cBuffer, iState, bError);
  689.         } // endif (strlen(cBuffer))
  690. __Done:
  691.     }
  692.     while (!feof(hFile) && !bError);
  693.  
  694.     fclose(hFile);
  695.  
  696.     if (iFirstTriangleOfFan) free(iFirstTriangleOfFan);
  697.  
  698.     if (bError)
  699.     {
  700.         vDeleteObjects();
  701.         return;
  702.     }
  703.  
  704.     // Calculer la plus grande dimension de la scène
  705.     fEnvSize = fEnvXmax - fEnvXmin;
  706.     if (fEnvYmax - fEnvYmin > fEnvSize) fEnvSize = fEnvYmax - fEnvYmin;
  707.     if (fEnvZmax - fEnvZmin > fEnvSize)    fEnvSize = fEnvZmax - fEnvZmin;
  708.  
  709.     // Normaliser les coordonnées de tous les points lus
  710.     for (int iVertex = 0 ; iVertex < iBaseVert + nVert ; iVertex++)
  711.     {
  712.         Vertices[iVertex].vPoint.x = ((Vertices[iVertex].vPoint.x - fEnvXmin - (fEnvXmax - fEnvXmin) / 2.f) * 8.f / fEnvSize);
  713.         Vertices[iVertex].vPoint.y = ((Vertices[iVertex].vPoint.y - fEnvYmin - (fEnvYmax - fEnvYmin) / 2.f) * 8.f / fEnvSize);
  714.         Vertices[iVertex].vPoint.z = ((Vertices[iVertex].vPoint.z - fEnvZmin - (fEnvZmax - fEnvZmin) / 2.f) * 8.f / fEnvSize);
  715.     }
  716.  
  717.     // Référencer les matériaux aux textures
  718.     vXRefMaterials2Textures();
  719.  
  720.     // Mapper les u/v des vertices sur les triangles
  721.     for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  722.     {
  723.         gTri    *hTri   = &(Triangles[iTriangle]);
  724.         gMtrl   *hMtrl  = &(Materials[hTri -> iMtrl]);
  725.         gTex    *hTex   = &(Textures[hMtrl -> iTexture]);
  726.  
  727.         for (i1 = 0 ; i1 < 3 ; i1++)
  728.         {
  729.             gSommet *hPoint = &(Vertices[hTri -> iSommets[i1]]);
  730.             hTri -> u[i1] = (short) (hPoint -> vPointBack.x * (float) (hTex -> iWidth - 1));
  731.             hTri -> v[i1] = (short) (hPoint -> vPointBack.y * (float) (hTex -> iHeight - 1));
  732.         }
  733.     }
  734.  
  735.     // Redessiner la 3D
  736.     vForce3DRefresh(XDC_MODE_COMPLET);
  737. }
  738.  
  739.